home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _9220CD64A58F49DAA8853D81A77B06E1 < prev    next >
Encoding:
Text File  |  2002-06-19  |  13.5 KB  |  522 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // cg_scoreboard -- draw the scoreboard on top of the game screen
  4. #include "cg_local.h"
  5.  
  6.  
  7. #define SB_HEADER            86
  8. #define SB_TOP                (SB_HEADER+32)
  9.  
  10. // Where the status bar starts, so we don't overwrite it
  11. #define SB_STATUSBAR        420
  12.  
  13. #define SB_MAXCLIENTS_NORMAL  12
  14. #define SB_MAXCLIENTS_MORE      26
  15. #define SB_MAXCLIENTS_ALOT      32
  16.  
  17. // Used when interleaved
  18. #define SB_HEADER_WIDTH        (580)
  19. #define SB_HEADER_HEIGHT    30
  20. #define SB_HEADER_X            ((640-SB_HEADER_WIDTH)/2)
  21. #define SB_HEADER_Y            86
  22. #define SB_SCORELINE_X        (SB_HEADER_X+30)
  23. #define SB_SCORELINE_Y        120
  24. #define SB_SCORELINE_WIDTH    (SB_HEADER_WIDTH-60)
  25. #define SB_NAME_X            (SB_SCORELINE_X)
  26. #define SB_SCORE_X            (SB_SCORELINE_X+287)
  27. #define SB_KILLS_X            (SB_SCORELINE_X+335)
  28. #define SB_DEATHS_X            (SB_SCORELINE_X+384)
  29. #define    SB_PING_X            (SB_SCORELINE_X+440)
  30. #define SB_TIME_X            (SB_SCORELINE_X+489)
  31.  
  32. int        sb_lineHeight;
  33. int        sb_maxClients;
  34. float    sb_nameFontScale;
  35. float    sb_numberFontScale;
  36. float    sb_readyFontScale;
  37.  
  38. /*
  39. =================
  40. CG_DrawClientScore
  41. =================
  42. */
  43. static void CG_DrawClientScore( float x, float y, float w, score_t* score, float* color )
  44. {
  45.     clientInfo_t*    ci;
  46.     vec4_t            dataColor;
  47.     vec4_t            nameColor;
  48.     const char*        s;
  49.     float            f;
  50.  
  51.     nameColor[3] = dataColor[3] = 1.0f;
  52.     
  53.     // Validate the score
  54.     if ( score->client < 0 || score->client >= cgs.maxclients ) 
  55.     {
  56.         Com_Printf( "Bad score->client: %i\n", score->client );
  57.         return;
  58.     }
  59.  
  60.     // Convienience    
  61.     ci = &cgs.clientinfo[score->client];
  62.  
  63.     CG_DrawPic ( x - 5, y, w, sb_lineHeight, cgs.media.scoreboardLine );
  64.  
  65.     // highlight your position
  66.     if ( score->client == cg.snap->ps.clientNum ) 
  67.     {
  68.         vec4_t hcolor;
  69.  
  70.         hcolor[0] = 1.0f;
  71.         hcolor[1] = 1.0f;
  72.         hcolor[2] = 1.0f;
  73.         hcolor[3] = .10f;
  74.  
  75.         CG_FillRect( x - 5, y, w, sb_lineHeight, hcolor );
  76.  
  77.         VectorSet ( nameColor, 1.0f, 1.0f, 1.0f );
  78.         VectorSet ( dataColor, 0.5f, 0.5f, 0.5f );
  79.     }
  80.     else if ( (cg.snap->ps.pm_type == PM_DEAD) && score->client == cg.snap->ps.persistant[PERS_ATTACKER] )
  81.     {
  82.         vec4_t hcolor;
  83.  
  84.         hcolor[0] = 1.0f;
  85.         hcolor[1] = 1.0f;
  86.         hcolor[2] = 1.0f;
  87.         hcolor[3] = .10f;
  88.  
  89.         CG_FillRect( x - 5, y, w, sb_lineHeight, hcolor );
  90.  
  91.         VectorCopy ( color, nameColor );
  92.         VectorSet ( dataColor, 0.5f, 0.5f, 0.5f );
  93.     }
  94.     else
  95.     {
  96.         VectorCopy ( color, nameColor );
  97.         VectorSet ( dataColor, 0.3f, 0.3f, 0.3f );
  98.  
  99.         if ( ci->ghost )
  100.         {
  101.             VectorScale ( nameColor, 0.6f, nameColor );
  102.         }
  103.     }
  104.  
  105.     CG_DrawText( x, y, cgs.media.hudFont, sb_nameFontScale, nameColor, ci->name, 24, DT_OUTLINE );
  106.  
  107.     s = va("%i", score->score );
  108.     f = trap_R_GetTextWidth ( s, cgs.media.hudFont, sb_nameFontScale, 0 );
  109.     CG_DrawText( x + w - 10 - f, y, cgs.media.hudFont, sb_nameFontScale, nameColor, va("%i", score->score), 0, DT_OUTLINE );
  110.  
  111.     // Draw skull if dead and not in intermission
  112.     if ( cg.snap->ps.pm_type == PM_INTERMISSION  )
  113.     {
  114.         if ( cg.snap->ps.stats[ STAT_CLIENTS_READY ] & ( 1 << score->client ) )
  115.         {
  116.             vec3_t deadColor;
  117.             deadColor[0] = 0.60f;
  118.             deadColor[1] = 0.60f;
  119.             deadColor[2] = 0.60f;
  120.             deadColor[3] = 1.0f;
  121.             CG_DrawText( x + w - 70, y + 3, cgs.media.hudFont, sb_readyFontScale, deadColor, "READY", 0, DT_OUTLINE );
  122.         }
  123.     }
  124.     else if ( ci->ghost )
  125.     {
  126.         CG_DrawPic ( x + w - 70, y + 1, sb_numberFontScale * 0.8f, sb_numberFontScale * 0.8f, cgs.media.deadShader );            
  127.     }
  128.     // Draw any gametype items the guy is carrying
  129.     else
  130.     {
  131.         float xx = x + w - 70;
  132.         int   i;
  133.         for ( i = 0; i < MAX_GAMETYPE_ITEMS; i ++ )
  134.         {
  135.             centity_t* cent;
  136.  
  137.             cent = CG_GetEntity ( score->client);
  138.  
  139.             // No have item, no draw it
  140.             if ( !(ci->gametypeitems & (1<<i) ) )
  141.             {
  142.                 continue;
  143.             }
  144.  
  145.             if ( !cg_items[MODELINDEX_GAMETYPE_ITEM+i].icon )
  146.             {
  147.                 continue;
  148.             }
  149.  
  150.             CG_DrawPic ( xx, y + 1, sb_numberFontScale * 0.8f, sb_numberFontScale * 0.8f, cg_items[MODELINDEX_GAMETYPE_ITEM+i].icon );
  151.  
  152.             xx += sb_numberFontScale;
  153.         }
  154.     }        
  155.  
  156.  
  157.     s = va("%i/%i", score->kills, score->deaths);
  158.     f = trap_R_GetTextWidth ( s, cgs.media.hudFont, sb_readyFontScale, 0 );
  159.     CG_DrawText( x + w - 10 - f, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, s, 0, 0 );
  160.  
  161.     CG_DrawText( x, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("id: %i", score->client ), 0, 0 );
  162.     CG_DrawText( x + 40, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("ping: %i", score->ping ), 0, 0 );
  163.     CG_DrawText( x + 95, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("time: %i", score->time ), 0, 0 );
  164.  
  165.     if ( score->teamkillDamage )
  166.     {
  167.         CG_DrawText( x + 150, y + sb_numberFontScale, cgs.media.hudFont, sb_readyFontScale, dataColor, va("tk: %i%%", score->teamkillDamage ), 0, 0 );
  168.     }
  169. }
  170.  
  171. /*
  172. =================
  173. CG_TeamScoreboard
  174. =================
  175. */
  176. static int CG_TeamScoreboard( float x, float y, float w, team_t team ) 
  177. {
  178.     int                i;
  179.     int                skipped;
  180.     float            color[4];
  181.     int                count;
  182.     clientInfo_t    *ci;
  183.     const char*        s;
  184.     int                players;
  185.     qboolean        drawnClient;
  186.  
  187.     // Do we make sure the current client is drawn?
  188.     drawnClient = qtrue;
  189.     if ( cg.scores [ cg.snap->ps.clientNum ].team == team )
  190.     {
  191.         drawnClient = qfalse;
  192.     }
  193.  
  194.     // Determine the color for this team
  195.     switch ( team )
  196.     {
  197.         case TEAM_RED:
  198.             VectorCopy4 ( g_color_table[ColorIndex(COLOR_RED)], color );
  199.             break;
  200.  
  201.         case TEAM_BLUE:
  202.             VectorCopy4 ( g_color_table[ColorIndex(COLOR_BLUE)], color );
  203.             break;
  204.  
  205.         case TEAM_FREE:
  206.             VectorCopy4 ( g_color_table[ColorIndex(COLOR_GREEN)], color );
  207.             break;
  208.  
  209.         case TEAM_SPECTATOR:
  210.         default:
  211.             VectorCopy4 ( colorWhite, color );
  212.             break;
  213.     }
  214.  
  215.     // Draw as many clients as we can for this team
  216.     for ( skipped = -1, count = 0, i = 0 ; i < cg.numScores && count < sb_maxClients ; i++ ) 
  217.     {
  218.         score_t*    score;
  219.  
  220.         score = &cg.scores[i];
  221.         ci    = &cgs.clientinfo[ score->client ];
  222.  
  223.         if ( team != score->team ) 
  224.         {
  225.             continue;
  226.         }
  227.  
  228.         if ( count == sb_maxClients - 1 && !drawnClient )
  229.         {
  230.             if ( score->client != cg.snap->ps.clientNum )
  231.             {
  232.                 skipped = i;
  233.                 continue;
  234.             }
  235.             
  236.             drawnClient = qtrue; 
  237.         }
  238.  
  239.         CG_DrawClientScore( x, y + SB_HEADER_HEIGHT + sb_lineHeight * count, w, score, color );
  240.  
  241.         count++;
  242.     }
  243.  
  244.     if ( skipped != -1 &&  count < sb_maxClients )
  245.     {
  246.         CG_DrawClientScore( x, y + SB_HEADER_HEIGHT + sb_lineHeight * count, w, &cg.scores[skipped], color );
  247.  
  248.         count++;
  249.     }
  250.  
  251.     s = "";
  252.     switch ( team )
  253.     {
  254.         case TEAM_RED:
  255.             s = "RED TEAM";
  256.             players = ui_info_redcount.integer;
  257.             break;
  258.  
  259.         case TEAM_BLUE:
  260.             s = "BLUE TEAM";
  261.             players = ui_info_bluecount.integer;
  262.             break;
  263.  
  264.         case TEAM_FREE:
  265.             s = "PLAYERS";
  266.             players = ui_info_freecount.integer;
  267.             break;
  268.  
  269.         default:
  270.         case TEAM_SPECTATOR:
  271.             s = "SPECTATORS";
  272.             players = ui_info_speccount.integer;
  273.             break;
  274.     }
  275.  
  276.     // Use the same team color here, but alpha it a bit.
  277.     color[3] = 0.6f;
  278.  
  279.     // Draw the header information for this team
  280.     CG_DrawPic ( x - 5, y, w, 25, cgs.media.scoreboardHeader );
  281.     CG_FillRect( x - 5, y, w, 25, color );
  282.     CG_DrawText ( x, y, cgs.media.hudFont, 0.40f, colorWhite, va("%s", s), 0, 0 );
  283.     CG_DrawText ( x, y + 13, cgs.media.hudFont, 0.30f, colorWhite, va("players: %d", players), 0, 0 );
  284.  
  285.     // Draw the totals if this is the red or blue team
  286.     if ( (team == TEAM_RED || team == TEAM_BLUE))
  287.     {
  288.         const char* s;
  289.         float        f;
  290.  
  291.         s = va("%d",(cg.teamScores[team-TEAM_RED]));
  292.         f = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.43f, 0 );
  293.         CG_DrawText ( x + w - 10 - f, y, cgs.media.hudFont, 0.43f, colorWhite, s, 0, DT_OUTLINE );
  294.     }
  295.  
  296.     if ( count )
  297.     {
  298.         CG_DrawPic ( x - 5, y + SB_HEADER_HEIGHT + sb_lineHeight * count, w, sb_lineHeight, cgs.media.scoreboardFooter );
  299.     }
  300.     
  301.     y = count * sb_lineHeight + y + 10;
  302.  
  303.     if ( y > cg.scoreBoardBottom )
  304.     {
  305.         cg.scoreBoardBottom = y;
  306.     }
  307.  
  308.     return y;
  309. }
  310.  
  311. /*
  312. =================
  313. CG_DrawNormalScoreboard
  314.  
  315. Draws a scoreboard that has no teams
  316. =================
  317. */
  318. qboolean CG_DrawNormalScoreboard ( float y )
  319. {
  320.     cg.scoreBoardBottom = 0;
  321.  
  322.     // DRaw the game timer and the game type
  323.     CG_DrawText ( 385,  y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, "Game Time:", 0, DT_OUTLINE );
  324.     CG_DrawTimer ( 455,  y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, DT_OUTLINE, cg.time - cgs.levelStartTime );
  325.     CG_DrawText ( 150,  y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, cgs.gametypeData->displayName, 0, DT_OUTLINE );
  326.  
  327.     if ( ui_info_speccount.integer )
  328.     {
  329.         CG_FillRect ( 0, 470, 640, 10, colorBlack );
  330.         CG_DrawText ( 5, 470, cgs.media.hudFont, 0.30f, colorWhite, va("SPECTATORS:   %s", cg.scoreBoardSpectators), 0, 0 );
  331.     }
  332.  
  333.     if ( ui_info_freecount.integer > 10 ) 
  334.     {
  335.         sb_maxClients       = 16;
  336.         sb_lineHeight       = 20;
  337.         sb_nameFontScale   = 0.35f;
  338.         sb_readyFontScale  = 0.30f;
  339.         sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 );
  340.     } 
  341.     else
  342.     {
  343.         sb_maxClients       = 10;
  344.         sb_lineHeight       = 30;
  345.         sb_nameFontScale   = 0.43f;
  346.         sb_readyFontScale  = 0.30f;
  347.         sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 ) + 4;
  348.     }
  349.  
  350.     CG_TeamScoreboard ( 150, y, 350, TEAM_FREE );
  351.  
  352.     return qtrue;
  353. }
  354.  
  355. /*
  356. =================
  357. CG_DrawTeamScoreboard
  358.  
  359. Draw the normal in-game scoreboard
  360. =================
  361. */
  362. qboolean CG_DrawTeamScoreboard( float y ) 
  363. {
  364.     qboolean redFirst = qfalse;
  365.  
  366.     cg.scoreBoardBottom = 0;
  367.  
  368.     // DRaw the game timer and the game type
  369.     CG_DrawText ( 470,  y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, "Game Time:", 0, DT_OUTLINE );
  370.     CG_DrawTimer ( 540,  y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, DT_OUTLINE, cg.time - cgs.levelStartTime );
  371.     CG_DrawText ( 60,  y - 14, cgs.media.hudFont, 0.38f, colorLtGrey, cgs.gametypeData->displayName, 0, DT_OUTLINE );
  372.  
  373.     if ( ui_info_speccount.integer )
  374.     {
  375.         CG_FillRect ( 0, 470, 640, 10, colorBlack );
  376.         CG_DrawText ( 5, 470, cgs.media.hudFont, 0.30f, colorWhite, va("SPECTATORS:   %s", cg.scoreBoardSpectators), 0, 0 );
  377.     }
  378.  
  379.     if ( ui_info_redcount.integer > 10 || ui_info_bluecount.integer > 10 ) 
  380.     {
  381.         sb_maxClients       = 16;
  382.         sb_lineHeight       = 20;
  383.         sb_nameFontScale   = 0.35f;
  384.         sb_readyFontScale  = 0.30f;
  385.         sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 );
  386.     } 
  387.     else
  388.     {
  389.         sb_maxClients       = 10;
  390.         sb_lineHeight       = 30;
  391.         sb_nameFontScale   = 0.43f;
  392.         sb_readyFontScale  = 0.30f;
  393.         sb_numberFontScale = trap_R_GetTextHeight ( "W", cgs.media.hudFont, sb_nameFontScale, 0 ) + 4;
  394.     }
  395.  
  396.     // If there are more scores than the scoreboard can show then show the 
  397.     // players team first rather than the winning team
  398.     if ( cgs.clientinfo[cg.clientNum].team == TEAM_SPECTATOR )
  399.     {
  400.         if ( cg.teamScores[0] >= cg.teamScores[1] )
  401.         {
  402.             redFirst = qtrue;
  403.         }
  404.     }
  405.     else if ( cgs.clientinfo[cg.clientNum].team == TEAM_RED )
  406.     {
  407.         redFirst = qtrue;
  408.     }
  409.  
  410.     if ( redFirst ) 
  411.     {
  412.         CG_TeamScoreboard( 50, y, 265, TEAM_RED );
  413.         CG_TeamScoreboard( 330, y, 265, TEAM_BLUE );
  414.     }
  415.     else
  416.     {
  417.         CG_TeamScoreboard( 330, y, 265, TEAM_RED );
  418.         CG_TeamScoreboard( 50, y, 265, TEAM_BLUE );
  419.     }
  420.  
  421.     return qtrue;
  422. }
  423.  
  424. /*
  425. =================
  426. CG_DrawScoreboard
  427.  
  428. Draws either a team or a normal scoreboard
  429. =================
  430. */
  431. qboolean CG_DrawScoreboard ( void )
  432. {
  433.     float y;
  434.     float w;
  435.  
  436.     // don't draw amuthing if the menu or console is up
  437.     if ( cg_paused.integer ) 
  438.     {
  439.         cg.deferredPlayerLoading = 0;
  440.         return qfalse;
  441.     }
  442.  
  443.     // don't draw scoreboard during death while warmup up
  444.     if ( cg.warmup && !cg.showScores ) 
  445.     {
  446.         return qfalse;
  447.     }
  448.  
  449.     if ( !cg.showScores                                        && 
  450.          cg.predictedPlayerState.pm_type != PM_DEAD            &&
  451.          cg.predictedPlayerState.pm_type != PM_INTERMISSION    ) 
  452.     {
  453.         return qfalse;
  454.     }
  455.  
  456.     // scoreboard
  457.     y = 45;
  458.  
  459.     if ( cgs.gametypeData->teams )
  460.     {
  461.         if ( ui_info_redcount.integer < 10 && ui_info_bluecount.integer < 10 )
  462.         {
  463.             y += 50;
  464.         }
  465.     }
  466.     else if ( ui_info_freecount.integer < 10 )
  467.     {
  468.         y += 50;
  469.     }
  470.  
  471.     // Draw any gameover text
  472.     if ( cgs.gameover[0] )
  473.     {
  474.         w = trap_R_GetTextWidth ( cgs.gameover, cgs.media.hudFont, 0.48f, 0 );
  475.         CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, cgs.gameover, 0, DT_OUTLINE );
  476.     }
  477.     else if ( cgs.gametypeMessageTime > cg.time )
  478.     {
  479.         w = trap_R_GetTextWidth ( cgs.gametypeMessage, cgs.media.hudFont, 0.48f, 0 );
  480.         CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, cgs.gametypeMessage, 0, DT_OUTLINE );
  481.     }
  482.     // Should we draw who killed you?
  483.     else if ( cg.snap->ps.pm_type == PM_DEAD && 
  484.               cg.snap->ps.persistant[PERS_ATTACKER] < MAX_CLIENTS &&
  485.               cg.snap->ps.persistant[PERS_ATTACKER] != cg.snap->ps.clientNum )
  486.     {
  487.         const char* s;
  488.         s = va("Killed by %s", cgs.clientinfo[cg.snap->ps.persistant[PERS_ATTACKER]].name );
  489.         w = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.48f, 0 );
  490.         CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, s, 0, DT_OUTLINE );
  491.     }
  492.     else if ( cgs.gametypeData->teams )
  493.     {
  494.         const char* s;
  495.         if ( cg.teamScores[0] == cg.teamScores[1] )
  496.         {
  497.             s = va ( "Game Tied at %d", cg.teamScores[0] );
  498.         }
  499.         else if ( cg.teamScores[0] > cg.teamScores[1] )
  500.         {
  501.             s = va ( "Red leads Blue by %d", cg.teamScores[0] - cg.teamScores[1] );
  502.         }
  503.         else
  504.         {
  505.             s = va ( "Blue leads Red by %d", cg.teamScores[1] - cg.teamScores[0] );
  506.         }
  507.  
  508.         w = trap_R_GetTextWidth ( s, cgs.media.hudFont, 0.48f, 0 );
  509.         CG_DrawText ( 320 - w / 2, y - 30, cgs.media.hudFont, 0.48f, colorWhite, s, 0, DT_OUTLINE );
  510.     }        
  511.  
  512.     // load any models that have been deferred
  513.     cg.deferredPlayerLoading++;
  514.  
  515.     if ( cgs.gametypeData->teams )
  516.     {
  517.         return CG_DrawTeamScoreboard ( y );
  518.     }
  519.  
  520.     return CG_DrawNormalScoreboard ( y ); 
  521. }
  522.